#!/usr/bin/env python
'''A PyGame, kiosk-style client for PyLibrarian'''

import sys
import ConfigParser
import pygame
import database
from time import time, sleep

config = ConfigParser.ConfigParser()
config.readfp(open('config.ini'))

libraryName = config.get('library', 'name')
timeout = config.getint('client', 'session_timeout')

pygame.init()
size = width, height = config.getint('client', 'screen_width'), config.getint('client', 'screen_height')
screen = pygame.display.set_mode(size, pygame.FULLSCREEN)
#screen = pygame.display.set_mode(size)

black = 0, 0, 0
white = 255, 255, 255
green = 0, 255, 0
red = 255, 0, 0

titleFont = pygame.font.SysFont('Arial', 36)
normalFont = pygame.font.SysFont('Arial', 24)

LOGGED_OUT = 0
LOGGED_IN = 1
state = LOGGED_OUT
user = None

def attemptLogin(id):
  global user
  user = database.getUserByID(int(id))
  
  return LOGGED_IN if bool(user) else LOGGED_OUT

def displayConfirmation(message):
  text = normalFont.render(message, True, green)
  textpos = text.get_rect()
  textpos.centerx = screen.get_rect().centerx
  textpos.y = height - 42
  screen.blit(text, textpos)
  
  pygame.display.flip()
  sleep(1)

def displayError(message):
  text = normalFont.render(message, True, red)
  textpos = text.get_rect()
  textpos.centerx = screen.get_rect().centerx
  textpos.y = height - 42
  screen.blit(text, textpos)
  
  pygame.display.flip()
  sleep(1)
  pygame.event.clear()

def scanResource(id):
  global user
  
  try:
    if database.isResourceCheckedIn(id):
      result = database.checkoutResource(id, user.get('id'))
      if result:
        displayConfirmation('Checked out %s' % database.getResourceByID(id).get('title'))
    else:   # The book was already checked out, so check it in
      result = database.checkinResource(id)
      if result:
        displayConfirmation('Returned %s' % database.getResourceByID(id).get('title'))
    
    if not result:
      displayError('There was a problem scanning. You are probably scanning too fast.')
  except:
    import traceback
    print traceback.format_exc()
    displayError('There was a problem scanning. You are probably scanning too fast.')

def runKiosk():
  global state
  global user
  
  inputBuffer = ''
  lastScan = time()
  
  # Hide the mouse
  pygame.mouse.set_visible(False)
  
  while True:     # Main loop
    try:
      for event in pygame.event.get():
        if event.type == pygame.QUIT:
          sys.exit(0)
        elif event.type == pygame.KEYDOWN:      # A key event was received (from the scanner I hope)
          if event.key < 127:
            if event.key == pygame.K_q:         # A librarian plugged in a keyboard and pressed 'q' to quit
              sys.exit(0)   # quit
            elif event.key == pygame.K_l:
              state = LOGGED_OUT
            elif event.key == pygame.K_RETURN:  # A newline was received (end of scanned barcode)
              if state == LOGGED_OUT:           # Try to login if we are logged out
                state = attemptLogin(inputBuffer)
                if state == LOGGED_IN:
                  displayConfirmation('You may begin scanning books to check out or return')
              elif state == LOGGED_IN:
                if len(inputBuffer) == 8 and inputBuffer.isdigit():   # Try to log back out if we scanned a library card
                  state = LOGGED_OUT if int(inputBuffer) == user.get('id') else attemptLogin(inputBuffer)
                  if state == LOGGED_IN:
                    displayConfirmation('You may begin scanning books to check out or return')
                elif len(inputBuffer) == 9 and inputBuffer.isdigit(): # Try to check a book out or in if we scanned a book code
                  scanResource(inputBuffer)
                else:     # We scanned a book by barcode
                  loan = database.getISBNCheckedOutByUser(inputBuffer, user.get('id'))
                  if not loan:
                    scanResource(database.getAvailableResourceByISBN(inputBuffer).get('id'))
                  else:
                    scanResource(loan.get('resource_id'))
            
            if lastScan + 1 < time() or event.key == pygame.K_RETURN:   # If we have had no input for 1 second (reasonable with a barcode reader), clear the input buffer
              inputBuffer = ''
              
            inputBuffer += chr(event.key)
            lastScan = time()
        
      screen.fill(black)
      if state == LOGGED_OUT:
        text = titleFont.render('Welcome to the %s' % (libraryName), True, white)
        textpos = text.get_rect()
        textpos.centerx = screen.get_rect().centerx
        screen.blit(text, textpos)
        
        text = normalFont.render('Please scan your library card', True, white)
        textpos = text.get_rect()
        textpos.centerx = screen.get_rect().centerx
        textpos.y = 42
        screen.blit(text, textpos)
      elif state == LOGGED_IN:
        text = titleFont.render("Check Out Books", True, white)
        textpos = text.get_rect()
        textpos.centerx = screen.get_rect().centerx
        screen.blit(text, textpos)
        
        text = normalFont.render('Please scan a book, or scan your card again to finish', True, white)
        textpos = text.get_rect()
        textpos.centerx = screen.get_rect().centerx
        textpos.y = 42
        screen.blit(text, textpos)
        
        if time() > lastScan + timeout:
          state = LOGGED_OUT
      
      pygame.display.flip()
      sleep(1.0/100)
    except SystemExit:
      raise
    except:
      displayError('Oops, something really went wrong. Contact the librarian if problems continue')
runKiosk()